﻿#pragma once

struct ShaderSource {
	std::string vertex_shader_code;		// 顶点着色器代码
	std::string fragment_shader_code;	// 片元着色器代码
	std::string geometry_shader_code;	// 几何着色器代码
	std::string control_shader_code;	// 控制着色器代码
	std::string evaluation_shader_code;	// 评估着色器代码
	std::string compute_shader_code;	// 计算着色器代码
	ShaderSource();	// 构造函数
	ShaderSource(const ShaderSource& other); // 拷贝构造函数
	ShaderSource& operator=(const ShaderSource& other); // 赋值运算符
	void print(); // 打印着色器源代码
};

class Shader
{
private:
	ShaderSource m_source_code;		// 着色器源代码
	std::string m_filename;			// 便于调试用，记录着色器文件名
	uint32_t m_shader_renderer_id; 	// 着色器渲染器 ID
	//int m_location;					// 保存当前着色器程序中 uniform 变量的位置
	mutable std::unordered_map<std::string, int> m_uniform_location_map; // 字典，保存 uniform 变量的位置，mutable 关键字用于声明允许在 const 成员函数中修改变量

	ShaderSource parse_shader(const char* filename); // 解析着色器文件

	uint32_t compile_shader(uint32_t type, const std::string& source); // 编译着色器

	uint32_t create_shader(std::string& vertex_shader, std::string& fragment_shader);

public:
	Shader(const std::string& filename);
	//Shader(const std::string& name, const ShaderSource& source);
	~Shader();

	int get_uniform_location(const std::string& name) const; // 获取 uniform 变量的位置

	void use_program() const;	 // 使用着色器程序

	void not_use_program() const; // 解绑着色器（解除使用）

	//void set_bool(const std::string& name, bool value) const;

	void set_uniform4f(const std::string& name, float red, float green, float blue, float alpha) const; // 设置着色器颜色属性
	void set_uniform1f(const std::string& name, float v1) const; // 设置着色器颜色属性

	void set_uniform4f(int& location, float red, float green, float blue, float alpha) const; // 设置着色器三通道含透明度的颜色属性
	void set_uniform1f(int& location, float v1) const; // 设置着色器浮点数属性

	void set_uniform1i(const std::string& name, int v1) const; // 设置着色器整数属性（用于整数型向量）用于纹理属性
	void set_uniform1i(int& location, int v1) const; // 设置着色器整数属性，用于纹理属性

	void set_uniform_matrix4fv(int& location, const glm::mat4& matrix) const;

	void set_uniform_matrix4fv(const std::string& name, const glm::mat4& matrix) const; // 设置着色器矩阵属性
	//void set_uniform_matrix4fv(int& location, const glm::mat4& matrix) const; // 设置着色器矩阵属性

	ShaderSource& get_source_code(); // 获取着色器源代码
};
